<?php
namespace aop\core;

trait ConfigAbstractManagerTrait {

    use \aop\config\AOPAbstractConfig;

    private $_config_abstract_instance_bindings = [];
    private $_config_abstract_closure_bindings = [];

    private function _fetchAbstractConfig($bizName) {
        return isset($this->_abstract_config_map[$bizName]) ? $this->_abstract_config_map[$bizName] : [];
    }

    private function _fetchAbstractConfigConcret($bizName, $abstract, $methodName, array $bizAbstractMap) {
        if (isset($this->_config_abstract_instance_bindings[$bizName][$abstract])) {
            return $this->_config_abstract_instance_bindings[$bizName][$abstract];
        }
        if (!isset($bizAbstractMap[$abstract])) {
            return NULL;
        }

        $classReflection = new \ReflectionClass($bizAbstractMap[$abstract]);
        if (!$classReflection->hasMethod($methodName)) {
            return NULL;
        }
        $concret = $classReflection->isInstantiable() ? $classReflection->newInstance() : $classReflection->newInstanceWithoutConstructor();
        if ($classReflection->hasMethod('init')) {
            (function() {
                $this->init();
            })->call($concret);
        }
        isset($this->_config_abstract_instance_bindings[$bizName]) || $this->_config_abstract_instance_bindings[$bizName] = [];
        $this->_config_abstract_instance_bindings[$bizName][$abstract] = $concret;
        return $concret;
    }


    private function _hasConfigAbstractMethodClosure($bizName, $abstract, $method) {
        $configAbstractKey = $this->_createConfigAbstractKey($abstract, $method);
        return isset($this->_config_abstract_closure_bindings[$bizName][$configAbstractKey]) ? $this->_config_abstract_closure_bindings[$bizName][$configAbstractKey] : NULL;
    }

    private function _saveConfigAbstractMethodClosure($bizName, $abstract, $method, $closure) {
        $configAbstractKey = $this->_createConfigAbstractKey($abstract, $method);
        $this->_config_abstract_closure_bindings[$bizName][$configAbstractKey] = $closure;
    }

    private function _createConfigAbstractKey($abstract, $method) {
        return $abstract . '::' . $method;
    }

    private function _fetchEventClosureParam() {
        return [
            'execute_flag' => '',
            'class_name' => $this->_class_name,
            'method_name' => $this->_method_name,
            'method_param' => [],
            'param_rule' => '',
            'param_name_list' => [],
            'method_result' => NULL,
            'is_replace' => FALSE
        ];
    }
}